package com.aiwiown.snackmq.network.server;

import com.aiwiown.snackmq.network.config.NetworkConfig;
import com.aiwiown.snackmq.network.connection.ConnectionManager;
import com.aiwiown.snackmq.network.handler.HeartbeatHandler;
import com.aiwiown.snackmq.network.handler.MessageCodec;
import com.aiwiown.snackmq.network.handler.ServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * NettyServer 类负责初始化和启动基于 Netty 的服务器。
 * 它使用责任链模式处理通道中的不同职责，包括日志记录、心跳检测、消息编解码和业务逻辑处理。
 */
@Slf4j
public class NettyServer {

    // 网络配置
    private final NetworkConfig networkConfig;
    // ServerBootstrap 用于服务器的启动配置
    private final ServerBootstrap bootstrap;
    // bossGroup 用于处理连接请求
    private final EventLoopGroup bossGroup;
    // workerGroup 用于处理已连接的通道上的通信
    private final EventLoopGroup workerGroup;
    // 保存服务器启动后的 ChannelFuture，用于关闭服务器
    private ChannelFuture channelFuture;

    /**
     * 构造函数被重构，使其更加通用。
     * 它不再关心业务逻辑，只接收一个配置好的、可共享的业务处理器。
     *
     * @param networkConfig        网络配置
     * @param businessLogicHandler 一个可共享的 ChannelHandler，它包含了所有的业务逻辑（例如，MessageDispatcher）
     */
    public NettyServer(NetworkConfig networkConfig, final ChannelHandler businessLogicHandler) {
        // 2. 在构造函数开头添加参数校验
        Objects.requireNonNull(networkConfig, "networkConfig cannot be null");
        Objects.requireNonNull(businessLogicHandler, "businessLogicHandler cannot be null");
        this.networkConfig = networkConfig;
        this.bossGroup = new NioEventLoopGroup(1);
        this.workerGroup = new NioEventLoopGroup();
        this.bootstrap = new ServerBootstrap();

        // 创建可共享的连接管理处理器
        final ServerHandler connectionHandler = new ServerHandler(ConnectionManager.getInstance());

        // 配置服务器启动参数 (后续代码保持不变)
        bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 128)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ChannelPipeline pipeline = ch.pipeline();

                        // 添加 IdleStateHandler 用于检测空闲连接
                        pipeline.addLast(new IdleStateHandler(
                                networkConfig.getHeartbeatInterval() * 3L,
                                0,
                                0,
                                TimeUnit.MILLISECONDS));
                        // 添加 LengthFieldBasedFrameDecoder 用于处理基于长度域的消息帧
                        pipeline.addLast(new LengthFieldBasedFrameDecoder(2 * 1024 * 1024, 5, 4, 0, 0));

                        // 协议层
                        pipeline.addLast(new MessageCodec());
                        pipeline.addLast(new HeartbeatHandler(false));

                        // --- 依赖倒置的核心 ---
                        // 连接管理层
                        pipeline.addLast(connectionHandler);
                        // 业务逻辑层 (由外部注入)
                        pipeline.addLast(businessLogicHandler);
                    }
                });
    }

    /**
     * 启动服务器并绑定到配置的端口。
     * 如果启动过程中被中断，将记录错误并关闭服务器。
     */
    public void start() {
        try {
            this.channelFuture = bootstrap.bind(networkConfig.getPort()).sync();
            log.info("Server started on port: {}", networkConfig.getPort());
        } catch (InterruptedException e) {
            log.error("Server start interrupted", e);
            Thread.currentThread().interrupt();
            shutdown();
        }
    }

    /**
     * 关闭服务器，包括关闭通道和释放资源。
     * 如果在关闭通道时发生中断，将记录错误并释放资源。
     */
    public void shutdown() {
        log.info("Shutting down server...");
        try {
            if (channelFuture != null) {
                channelFuture.channel().close().sync();
            }
        } catch (InterruptedException e) {
            log.error("Error while closing server channel", e);
            Thread.currentThread().interrupt();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
            log.info("Server shutdown completed");
        }
    }
}
